package org.dousb.doupicture.infrastructure.utils;

import java.awt.*;

/**
 * 颜色相似度工具类
 * 基于欧式距离算法计算颜色相似度
 * 支持RGB颜色空间和多种颜色格式转换
 *
 * @version 1.0
 * @date 2024-10-10
 */
public class ColorSimilarityUtils {

    /**
     * 计算两个颜色之间的欧式距离
     * 距离越小表示颜色越相似，范围[0, √(3×255²)]
     *
     * @param color1 第一个颜色
     * @param color2 第二个颜色
     * @return 欧式距离值
     */
    public static double calculateEuclideanDistance(Color color1, Color color2) {
        if (color1 == null || color2 == null) {
            throw new IllegalArgumentException("颜色参数不能为null");
        }

        int r1 = color1.getRed();
        int g1 = color1.getGreen();
        int b1 = color1.getBlue();

        int r2 = color2.getRed();
        int g2 = color2.getGreen();
        int b2 = color2.getBlue();

        return Math.sqrt(Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2));
    }

    /**
     * 计算颜色相似度（百分比形式）
     * 相似度越大表示颜色越相似，范围[0, 1]
     *
     * @param color1 第一个颜色
     * @param color2 第二个颜色
     * @return 相似度百分比（0-1之间）
     */
    public static double calculateSimilarity(Color color1, Color color2) {
        double distance = calculateEuclideanDistance(color1, color2);
        // 最大可能距离：√(3×255²)
        double maxDistance = Math.sqrt(3 * Math.pow(255, 2));
        return 1 - (distance / maxDistance);
    }

    /**
     * 判断两个颜色是否相似（基于阈值判断）
     *
     * @param color1    第一个颜色
     * @param color2    第二个颜色
     * @param threshold 相似度阈值（0-1之间）
     * @return 如果相似度大于等于阈值返回true，否则返回false
     */
    public static boolean areColorsSimilar(Color color1, Color color2, double threshold) {
        if (threshold < 0 || threshold > 1) {
            throw new IllegalArgumentException("阈值必须在0-1之间");
        }
        double similarity = calculateSimilarity(color1, color2);
        return similarity >= threshold;
    }

    /**
     * 判断两个颜色是否相似（基于距离阈值）
     *
     * @param color1            第一个颜色
     * @param color2            第二个颜色
     * @param distanceThreshold 距离阈值（0-√(3×255²)之间）
     * @return 如果距离小于等于阈值返回true，否则返回false
     */
    public static boolean areColorsSimilarByDistance(Color color1, Color color2, double distanceThreshold) {
        if (distanceThreshold < 0) {
            throw new IllegalArgumentException("距离阈值必须大于等于0");
        }
        double distance = calculateEuclideanDistance(color1, color2);
        return distance <= distanceThreshold;
    }

    /**
     * 将十六进制颜色字符串转换为Color对象
     *
     * @param hexColor 十六进制颜色字符串（格式如：#FF0000或FF0000）
     * @return 对应的Color对象
     */
    public static Color hexToColor(String hexColor) {
        if (hexColor == null || hexColor.trim().isEmpty()) {
            throw new IllegalArgumentException("十六进制颜色字符串不能为空");
        }

        String hex = hexColor.startsWith("#") ? hexColor.substring(1) : hexColor;

        if (hex.length() != 6) {
            throw new IllegalArgumentException("十六进制颜色字符串格式不正确，必须是6位字符");
        }

        try {
            int r = Integer.valueOf(hex.substring(0, 2), 16);
            int g = Integer.valueOf(hex.substring(2, 4), 16);
            int b = Integer.valueOf(hex.substring(4, 6), 16);

            return new Color(r, g, b);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("十六进制颜色字符串包含非法字符");
        }
    }

    /**
     * 将RGB数组转换为Color对象
     *
     * @param rgb RGB数组，长度为3，分别表示红、绿、蓝分量
     * @return 对应的Color对象
     */
    public static Color rgbArrayToColor(int[] rgb) {
        if (rgb == null || rgb.length != 3) {
            throw new IllegalArgumentException("RGB数组必须包含3个元素");
        }

        if (rgb[0] < 0 || rgb[0] > 255 || rgb[1] < 0 || rgb[1] > 255 || rgb[2] < 0 || rgb[2] > 255) {
            throw new IllegalArgumentException("RGB分量值必须在0-255之间");
        }

        return new Color(rgb[0], rgb[1], rgb[2]);
    }

    /**
     * 计算两个十六进制颜色字符串的相似度
     *
     * @param hexColor1 第一个十六进制颜色字符串
     * @param hexColor2 第二个十六进制颜色字符串
     * @return 相似度百分比（0-1之间）
     */
    public static double calculateHexSimilarity(String hexColor1, String hexColor2) {
        Color color1 = hexToColor(hexColor1);
        Color color2 = hexToColor(hexColor2);
        return calculateSimilarity(color1, color2);
    }

    /**
     * 计算两个RGB数组的相似度
     *
     * @param rgb1 第一个RGB数组
     * @param rgb2 第二个RGB数组
     * @return 相似度百分比（0-1之间）
     */
    public static double calculateRgbSimilarity(int[] rgb1, int[] rgb2) {
        Color color1 = rgbArrayToColor(rgb1);
        Color color2 = rgbArrayToColor(rgb2);
        return calculateSimilarity(color1, color2);
    }

    /**
     * 获取详细的颜色比较结果
     *
     * @param color1 第一个颜色
     * @param color2 第二个颜色
     * @return 包含距离、相似度和判断结果的字符串
     */
    public static String getDetailedComparison(Color color1, Color color2) {
        double distance = calculateEuclideanDistance(color1, color2);
        double similarity = calculateSimilarity(color1, color2);

        return String.format("颜色比较结果:\n" +
                        "欧式距离: %.2f\n" +
                        "相似度: %.2f%%\n" +
                        "颜色1 RGB: (%d, %d, %d)\n" +
                        "颜色2 RGB: (%d, %d, %d)",
                distance, similarity * 100,
                color1.getRed(), color1.getGreen(), color1.getBlue(),
                color2.getRed(), color2.getGreen(), color2.getBlue());
    }
}